package com.yanboo.config;


import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.yanboo.common.annotation.CustomController;
import com.yanboo.common.annotation.NonUnify;
import com.yanboo.common.base.UnifyResult;
import com.yanboo.common.utils.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.*;
import java.lang.reflect.Field;
import java.util.*;

/**
 * 只为适配使用习惯，jpa通常无需担心翻译问题
 */
@Component
@Slf4j
@ControllerAdvice
public class UnifyResultConfig implements ResponseBodyAdvice<Object> {
    public UnifyResultConfig(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        CustomController customController = returnType.getMethod().getDeclaringClass().getAnnotation(CustomController.class);
        if (Objects.isNull(customController)) {
            return false;
        }
        NonUnify methodNonUnify = returnType.getMethod().getAnnotation(NonUnify.class);
        NonUnify classNonUnify = returnType.getMethod().getDeclaringClass().getAnnotation(NonUnify.class);
        return !Objects.nonNull(classNonUnify) && !Objects.nonNull(methodNonUnify);
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        //封装返回结果
        if (Objects.isNull(body)) {
            return UnifyResult.builder().build();
        }

        if (body instanceof ModelAndView) {
            return (ModelAndView) body;
        }

        if (body instanceof UnifyResult) {
            return (UnifyResult<?>) body;
        }

        if (body instanceof Collection) {
            List<?> res = null;
            try {
                res = (List<?>) this.parseDictCollection(body);
            } catch (NoSuchFieldException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
            return UnifyResult.builder().size(res.size()).data(new ArrayList<>(res)).build();
        }
        if (body instanceof PageResult) {
            PageResult<?> pageResult = (PageResult<?>) body;
            List<?> res = null;
            try {
                res = (List<?>) this.parseDictText(pageResult.getContent());
            } catch (NoSuchFieldException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
            return UnifyResult.builder().total(pageResult.getTotalElements()).data(new ArrayList<>(res)).build();
        }
        request.getMethod();
        Object res = null;
        try {
            res = this.parseDictText(body);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }
        return UnifyResult.builder().code(200).data(Lists.newArrayList(res)).build();
    }

    private Object parseDictText(Object result) throws NoSuchFieldException, IllegalAccessException {
        if (result instanceof Collection) {
            return parseDictCollection(result);
        } else {
            result = parseDict(result);
            return result;
        }
    }


    private Object parseDictCollection(Object result) throws NoSuchFieldException, IllegalAccessException {
        List<Object> items = new ArrayList<>();
        for (Object record : ((Collection<?>) result)) {
            items.add(parseDict(record));
        }
        return items;
    }

    @PersistenceContext
    private final EntityManager entityManager;

    private Object parseDict(Object record) throws NoSuchFieldException, IllegalAccessException {
        if (Objects.isNull(record)) {
            return null;
        }
        ObjectMapper mapper = new ObjectMapper();
        String json = "{}";
        try {
            json = mapper.writeValueAsString(record);
        } catch (JsonProcessingException e) {
            log.error("json解析失败" + e.getMessage(), e);
        }
        JSONObject item;
        try {
            item = JSONObject.parseObject(json);
        } catch (JSONException exception) {
            return record;
        }
        boolean isDict = false;
        for (Field field : getAllFields(record)) {
            if (field.getAnnotation(com.yanboo.annotation.Dict.class) != null) {
                isDict = true;
                String key = field.getAnnotation(com.yanboo.annotation.Dict.class).key();
                String col = field.getAnnotation(com.yanboo.annotation.Dict.class).valCol();
                Class<?> entity = field.getAnnotation(com.yanboo.annotation.Dict.class).entity();
                String server = field.getAnnotation(com.yanboo.annotation.Dict.class).server();
                String keyVal = String.valueOf(item.get(field.getName()));
                String textValue = null;
                if (StringUtils.isEmpty(server)) {
                    // 本地访问
                    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
                    CriteriaQuery<?> query = cb.createQuery(entity);
                    Root<?> root = query.from(entity);
                    Path<?> keyCol = root.get(key);
                    Predicate predicateEmail = cb.equal(keyCol, keyVal);
                    query.where(predicateEmail);
                    TypedQuery<?> q = entityManager.createQuery(query);
                    List<?> results = q.getResultList();
                    if (Objects.isNull(results)) {
                        continue;
                    }
                    Object result = results.get(0);
                    Field declaredField = result.getClass().getDeclaredField(col);
                    Object o = declaredField.get(result);
                    textValue = String.valueOf(o);
                } else {
                    // 访问微服务
                    //TODO 微服务
                }
                //log.info(" 字典Val : " + textValue);
                log.info(" 翻译字典字段 " + field.getName() + "_dictText： " + textValue);
                item.put(field.getName() + "_dictText", textValue);
            }
        }
        if (isDict) {
            return item;
        } else {
            return record;
        }
    }

    /**
     * 获取类的所有属性，包括父类
     *
     * @param object
     * @return
     */
    private Field[] getAllFields(Object object) {
        Class<?> clazz = object.getClass();
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }
}
